from git import Repo
from pathlib import Path
from datetime import datetime
import ast
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import os
from collections import defaultdict
import matplotlib.dates as mdates

# 确保visuals目录存在
visuals_dir = Path("visuals")
visuals_dir.mkdir(exist_ok=True)

# 设置项目信息和链接
gitee_link = "https://gitee.com/"
repo_name = "openeuler-jenkins"
repo_link = gitee_link + "openeuler/openeuler-jenkins"
commits_link = gitee_link + "openeuler/openeuler-jenkins/commits/master"
authors_link = gitee_link + "openeuler/openeuler-jenkins/contributors"
branches_link = gitee_link + "openeuler/openeuler-jenkins/branches"
branch_link = gitee_link + "openeuler/openeuler-jenkins/tree/"

# 初始化Markdown报告
md = f"# {repo_name} Project Data Analysis\n\n"
md += "---\n\n"

# 克隆或加载本地仓库
if Path(repo_name).exists():
    repo = Repo(repo_name)
else:
    print("Cloning Repo...")
    repo = Repo.clone_from(repo_link, repo_name)
    print("Finished Cloning!")

# 项目基本信息
repo_commits = list(repo.iter_commits())
first_commit = repo_commits[-1]
latest_commit = repo_commits[0]
start_date = datetime.fromtimestamp(first_commit.authored_date)
latest_date = datetime.fromtimestamp(latest_commit.authored_date)

# 添加项目概览到报告
md += f"**Start Date:** {start_date}\n\n"
md += f"**Latest Update:** {latest_date}\n\n"
md += f"[**Commits:** {len(repo_commits)}]({commits_link})\n\n"

# 分支信息处理
gitee = repo.remotes[0]
gitee_branches = [ref.name[7:] for ref in gitee.refs if ref.name != "origin/HEAD"]
if "master" in gitee_branches:
    gitee_branches.remove("master")
repo_branches = ["master"] + gitee_branches
md += f"[**Branches:** {len(repo_branches)}]({branches_link})\n\n"

# 作者贡献统计
author_data = defaultdict(int)
for commit in repo_commits:
    author = commit.author.name
    author_data[author] += 1

author_data = sorted(author_data.items(), key=lambda x: x[1], reverse=True)
md += f"[**Authors:** {len(author_data)}]({authors_link})\n\n"

# -------------------- 数据准备 --------------------
# 准备提交日期和作者数据
commit_dates = []
commit_days = []
for commit in repo_commits:
    dt = datetime.fromtimestamp(commit.authored_date)
    commit_dates.append(dt)
    commit_days.append(dt.strftime("%A"))

# 按月统计提交
monthly_commits = defaultdict(int)
for dt in commit_dates:
    month_key = dt.strftime("%b %Y")
    monthly_commits[month_key] += 1

# 按星期统计提交
days_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
daily_commits = defaultdict(int)
for day in commit_days:
    daily_commits[day] += 1

# 累计提交
sorted_dates = sorted(commit_dates)
cumulative_commits = []
current_count = 0
cumulative_data = []
for i, dt in enumerate(sorted_dates):
    current_count += 1
    cumulative_data.append((dt, current_count))

# -------------------- 可视化 --------------------
try:
    plt.style.use('seaborn-v0_8')
except:
    sns.set()
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 1. Top 10 Contributors
plt.figure(figsize=(10, 6))
top_authors = author_data[:10]
authors = [x[0] for x in top_authors]
commits = [x[1] for x in top_authors]
plt.barh(authors[::-1], commits[::-1], color='skyblue')
plt.xlabel('提交次数')
plt.ylabel('贡献者')
plt.title('Top 10 贡献者')
plt.tight_layout()
plt.savefig(visuals_dir / 'top_contributors.png', dpi=300, bbox_inches='tight')
plt.close()
md += "![Top 10 Contributors](visuals/top_contributors.png)\n\n"

# 2. Commit Activity Over Last 12 Recorded Months
plt.figure(figsize=(12, 6))
sorted_months = sorted(monthly_commits.items(), key=lambda x: datetime.strptime(x[0], "%b %Y"))
last_12 = sorted_months[-12:]
months = [x[0] for x in last_12]
counts = [x[1] for x in last_12]
plt.plot(months, counts, marker='o', color='royalblue')
plt.xlabel('月份')
plt.ylabel('提交次数')
plt.title('过去12个月提交活动')
plt.xticks(rotation=45)
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.savefig(visuals_dir / 'monthly_commits.png', dpi=300, bbox_inches='tight')
plt.close()
md += "![Monthly Commits](visuals/monthly_commits.png)\n\n"

# 3. Commit Activity by Day of the Week
plt.figure(figsize=(10, 6))
days = days_order
counts = [daily_commits.get(day, 0) for day in days]
plt.bar(days, counts, color='lightgreen')
plt.xlabel('星期')
plt.ylabel('提交次数')
plt.title('按星期提交分布')
plt.tight_layout()
plt.savefig(visuals_dir / 'daily_commits.png', dpi=300, bbox_inches='tight')
plt.close()
md += "![Daily Commits](visuals/daily_commits.png)\n\n"

# 4. Cumulative Commit Growth
plt.figure(figsize=(12, 6))
dates = [x[0] for x in cumulative_data]
counts = [x[1] for x in cumulative_data]
plt.plot(dates, counts, color='darkorange')
plt.xlabel('日期')
plt.ylabel('累计提交')
plt.title('累计提交增长')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=3))
plt.grid(True, linestyle='--', alpha=0.7)
plt.tight_layout()
plt.savefig(visuals_dir / 'cumulative_commits.png', dpi=300, bbox_inches='tight')
plt.close()
md += "![Cumulative Commits](visuals/cumulative_commits.png)\n\n"

# 初始化数据存储列表
lines_changed = []
files_changed = []
commit_stats = []

# 从缓存文件读取或重新收集提交统计数据
if Path("commit_stats.txt").exists():
    print("READING FROM CACHE")
    with open("commit_stats.txt", "r") as file:
        commit_stats = file.readlines()
else:
    print("WRITING TO CACHE")
    with open("commit_stats.txt", "w") as file:
        for commit in repo_commits:
            stats = str(commit.stats.total)
            commit_stats.append(stats)
            file.write(f"{stats}\n")

# 解析统计数据
for stats in commit_stats:
    stat = ast.literal_eval(stats)
    lines_changed.append(stat['lines'])
    files_changed.append(stat['files'])

# 5. Distribution of Lines Changed Per Commit
plt.figure(figsize=(10, 6))
sns.boxplot(y=lines_changed, showfliers=False, color='lightblue')
plt.ylabel('变更行数')
plt.title('每次提交变更行数分布')
plt.tight_layout()
plt.savefig(visuals_dir / 'lines_changed.png', dpi=300, bbox_inches='tight')
plt.close()
md += "![Lines Changed](visuals/lines_changed.png)\n\n"

# 6. Distribution of Files Changed Per Commit
plt.figure(figsize=(10, 6))
sns.boxplot(y=files_changed, showfliers=False, color='lightpink')
plt.ylabel('变更文件数')
plt.title('每次提交变更文件数分布')
plt.tight_layout()
plt.savefig(visuals_dir / 'files_changed.png', dpi=300, bbox_inches='tight')
plt.close()
md += "![Files Changed](visuals/files_changed.png)\n\n"

# 添加提交统计分析到报告
md += "## Commit Stats\n\n"
mean_lines_changed = int(np.mean(lines_changed))
median_lines_changed = int(np.median(lines_changed))
mean_files_changed = int(np.mean(files_changed))
median_files_changed = int(np.median(files_changed))

md += f"**Average Lines Changed / Commit:** {mean_lines_changed}\n\n"
md += f"**Median Lines Changed / Commit:** {median_lines_changed}\n\n"
md += f"**Average Files Changed / Commit:** {mean_files_changed}\n\n"
md += f"**Median Files Changed / Commit:** {median_files_changed}\n\n"

# 添加分支列表到报告
md += "## Branches\n\n"
for branch in repo_branches:
    md += f"- [{branch}]({branch_link + branch})\n\n"

# 添加作者排行榜到报告
md += "## Top 10 Authors\n\n"
for i in range(min(10, len(author_data))):
    author = author_data[i]
    name = author[0].replace(" ", "")
    commits = author[1]
    md += f"{i + 1}. [{name}]({gitee_link + name}): {commits} commits\n\n"

# 写入Markdown文件
try:
    Path("report-openeuler-jenkins.md").write_text(md, "UTF-8")
    print("文件写入成功!")
except Exception as e:
    print(f"写入文件时出错: {e}")

print("Analysis complete! Report generated as report-openeuler-jenkins.md")